﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using PokeData;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using System.Timers;

namespace PokeTD
{
    class Waves
    {
        private List<Texture2D> creepTextures;
        private List<SoundEffect> creepSounds;

        private SoundEffect WaveClearedSoundEffect;

        private Timer t = new Timer();
        

        private List<Wave> waves = new List<Wave>();
        
        private int _currentWave;

        private float timeSinceLastWave = 0;
        private int _secondsToNextWave = 0;

        public event GameBeatenEventHandler OnGameBeaten;

        /// <summary>
        /// Lädt alle Waves aus der Datenbank.
        /// </summary>
        /// <param name="map">Referenz zur Map</param>
        /// <param name="creepTextures">Eine Liste von Creep-Texturen</param>
        public Waves(Map map, Player player, List<Texture2D> creepTextures, List<SoundEffect> creepSounds, SoundEffect WaveCleardEffect) {
            IEnumerable<DataRow> q = from s in Globals.waveDS.Waves
                                     select s;
            foreach (DataRow WaveRow in q) {
                Wave tw = new Wave(map, player, creepTextures[(int)WaveRow["CreepType"]], (int)WaveRow["id"], WaveRow["WaveName"].ToString(), (int)WaveRow["CreepType"], (int)WaveRow["CreepCount"], (int)WaveRow["SecondsToNextWave"], (double)WaveRow["SpawnTime"], creepSounds[(int)WaveRow["CreepType"]]);
                tw.OnWaveCleared += new WaveEventHandler(OnWaveCleared);
                waves.Add(tw);
            }
            this.creepTextures = creepTextures;
            this.creepSounds = creepSounds;
            this.WaveClearedSoundEffect = WaveCleardEffect;
            _currentWave = -1;
            t.Elapsed += new ElapsedEventHandler(t_Elapsed);
            t.Interval = 1500;
        }

        void t_Elapsed(object sender, ElapsedEventArgs e)
        {
            WaveClearedSoundEffect.Play();
            t.Stop();
        }

        public List<Wave> WavesList {
            get { return waves; }
            set { waves = value; }
        }
        public Wave CurrentWave {
            get { return waves[_currentWave]; }
        }
        public int secondsToNextWave {
            get {
                if (_currentWave == waves.Count - 1) return 0;
                else return _secondsToNextWave;
            }
        }
        public bool isStarted() {
            if (_currentWave < 0) {
                return false;
            }
            foreach (Wave wave in waves) {
                if (!wave.WaveCleared) {
                    return true;
                }
            }
            return false;
        }

        private void switchToWave(int Wave) {
            if ((Wave > waves.Count) || (Wave < 1)) {
                throw new System.ArgumentException("Wave nicht gefunden", "Wave");
            }
            // Gewünschte Wave einschalten
        }

        public void UpdatePaths() {
            foreach (Wave wave in waves) {
                if (!wave.WaveCleared) wave.UpdatePaths();
            }
        }
        /// <summary>
        /// Startet die nächste Wave.
        /// </summary>
        public void Next() {
            if (_currentWave < waves.Count - 1) {
                _currentWave++;
                timeSinceLastWave = 0;
                CurrentWave.Start();

                Globals.MessageSystem.AddMessage("Wave " + CurrentWave.Name + ": Spawne " + CurrentWave.CreepsToSpawn + " " + CurrentWave.Creeps[0].Name, Color.DarkGreen);
            }
            else {
                if(CurrentWave.WaveCleared)
                    OnGameBeaten(this, new GameBeatenEventArgs());
            }

        }

        public void Update(GameTime gameTime) {
            if (isStarted()) {
                foreach (Wave wave in waves) {
                    if (wave.WaveStarted && !wave.WaveCleared) wave.Update(gameTime);
                }
                timeSinceLastWave += (float)gameTime.ElapsedGameTime.TotalSeconds;
                _secondsToNextWave = (int)(CurrentWave.SecondsToNextWave - timeSinceLastWave); 
                if (timeSinceLastWave > (float)CurrentWave.SecondsToNextWave) {
                    Next();
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch, SpriteFont font) {
            if (isStarted()) {
                foreach (Wave wave in waves) {
                    if (wave.WaveStarted && !wave.WaveCleared) wave.Draw(spriteBatch, font);
                }
            }
        }

        public Map Map
        {
            set
            {
                foreach (Wave w in waves)
                {
                    w.Map = value;
                }
            }
        }
        public void OnWaveCleared(object sender, WaveEventArgs e)
        {
            if ((_currentWave == waves.Count - 1) && CurrentWave.WaveCleared)
            {
                OnGameBeaten(this, new GameBeatenEventArgs());
            }
            else
            {
                Wave s = (Wave)sender;
                Globals.MessageSystem.AddMessage("Wave \"" + s.Name + "\" beendet!", Color.Black);
                t.Start();
            }
        }
    }
}
